package com.chaos.auth.controller;

import cn.hutool.core.util.ObjectUtil;
import com.chaos.auth.api.data.RbacUserData;
import com.chaos.auth.api.data.RbacUserRoleData;
import com.chaos.auth.api.dto.auth.RbacUserDto;
import com.chaos.auth.entity.RbacUserRole;
import com.chaos.auth.service.RbacUserRoleService;
import com.chaos.auth.service.RbacUserService;
import com.chaos.framework.model.dto.DTO;
import com.chaos.framework.model.dto.ID;
import com.chaos.framework.model.dto.page.PageList;
import com.chaos.framework.model.dto.page.PageQueryDto;
import com.chaos.framework.model.dto.result.data.BooleanResult;
import com.chaos.framework.model.dto.result.data.DataResult;
import com.chaos.framework.model.dto.result.list.ListResult;
import com.chaos.framework.model.dto.result.page.PageResult;
import com.chaos.framework.model.enums.ResultEnum;
import com.chaos.framework.model.exception.BusinessException;
import com.chaos.framework.starter.base.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Jacky.Cui
 * @since 2024-11-13
 */
@Slf4j
@RestController
@Api(tags = "")
@RequestMapping("/rbacUser")
public class RbacUserController extends BaseController<RbacUserData> {
    @Resource
    private RbacUserService rbacUserService;
    @Resource
    PasswordEncoder passwordEncoder;
    @Resource
    private RbacUserRoleService rbacUserRoleService;

    @PostMapping("/one.admin")
    @ApiOperation(value = "详情", httpMethod = "POST")
    public DataResult<RbacUserData> one(@RequestBody @Valid ID data) {
        RbacUserData entity = rbacUserService.selectByID(data);
        entity.setPassword("");
        return dataResult(entity);
    }

    @PostMapping("/list.admin")
    @ApiOperation(value = "列表", httpMethod = "POST")
    public ListResult<RbacUserData> list(@RequestBody @Valid RbacUserData data) {
        List<RbacUserData> entities = rbacUserService.selectByData(data);
        entities.forEach(e -> e.setPassword(""));
        return listResult(entities);
    }

    @PostMapping("/page.admin")
    @ApiOperation(value = "分页", httpMethod = "POST")
    public PageResult<RbacUserData> page(@RequestBody @Valid PageQueryDto<RbacUserData> data) {
        PageList<RbacUserData> page = rbacUserService.selectByPage(data);
        List<RbacUserData> entities = page.getList();
        entities.forEach(e -> e.setPassword(""));
        return pageResult(page);
    }

    @PostMapping("/add.admin")
    @ApiOperation(value = "新增", httpMethod = "POST")
    public DataResult<ID> add(@RequestBody @Valid RbacUserDto data) {
        String username = data.getUsername();
        if (ObjectUtil.isNotEmpty(username)) {
            RbacUserData userData = RbacUserData.builder().username(username).build();
            List<RbacUserData> user = rbacUserService.selectByData(userData);
            if (ObjectUtil.isNotEmpty(user)) {
                throw new BusinessException(ResultEnum.SQL_DUPLICATE_KEY.getCode(), "用户已存在");
            }
        }
        dealPassword(data);
        dealValidityPeriod(data);
        ID id = rbacUserService.insertModel(data);

        if (ObjectUtil.isNotEmpty(data.getRoles())) {
            data.getRoles().forEach(roleId -> rbacUserRoleService.insertModel(RbacUserRoleData.builder().userId(id.getId()).roleId(roleId).build()));
        }
        return dataResult(id);
    }

    private void dealPassword(RbacUserDto data) {


        String password = data.getPassword();
        if (ObjectUtil.isNotEmpty(password)) {
            String originalPassword = data.getOriginalPassword();
            RbacUserData entity = rbacUserService.selectByID(new ID(data.getId()));
            if (!passwordEncoder.matches(originalPassword, entity.getPassword())) {
                throw new BusinessException(ResultEnum.WRONG_PASSWORD);
            }

            String encoderPassword = passwordEncoder.encode(password);
            data.setPassword(encoderPassword);
        }
    }

    private static void dealValidityPeriod(RbacUserDto data) {
        if (ObjectUtil.isNotEmpty(data.getValidityPeriod())) {
            List<LocalDateTime> dates = data.getValidityPeriod();
            data.setValidityPeriodBegin(dates.get(0));
            data.setValidityPeriodEnd(dates.get(1));
        }
    }

    @PostMapping("/update.admin")
    @ApiOperation(value = "编辑", httpMethod = "POST")
    public BooleanResult update(@RequestBody @Valid RbacUserDto data) {
        dealRoles(data);
        dealValidityPeriod(data);
        dealPassword(data);
        return booleanResult(rbacUserService.updateModelByID(data));
    }

    private void dealRoles(RbacUserDto data) {
        List<Long> roleIds = data.getRoles();
        if (ObjectUtil.isEmpty(roleIds)) return;
        List<RbacUserRoleData> userRoles = rbacUserRoleService.selectByData(RbacUserRoleData.builder().userId(data.getId()).build());
        Set<Long> currentRoleIds = userRoles.stream().map(RbacUserRoleData::getRoleId).collect(Collectors.toSet());


        // 找出需要删除的角色 ID
        Set<Long> rolesToDelete = new HashSet<>(currentRoleIds);
        rolesToDelete.removeAll(roleIds);

        // 找出需要添加的角色 ID
        Set<Long> rolesToAdd = new HashSet<>(roleIds);
        rolesToAdd.removeAll(currentRoleIds);

        // 删除多余的角色
        if (!rolesToDelete.isEmpty()) {
            List<RbacUserRoleData> rolesToDeleteList = userRoles.stream().filter(userRole -> rolesToDelete.contains(userRole.getRoleId())).collect(Collectors.toList());
            rolesToDeleteList.stream().forEach(e -> rbacUserRoleService.deleteModel(new ID(e.getId())));
        }

        // 添加缺少的角色
        if (!rolesToAdd.isEmpty()) {
            List<RbacUserRole> rolesToAddList = rolesToAdd.stream().map(roleId -> RbacUserRole.builder().userId(data.getId()).roleId(roleId).build()).collect(Collectors.toList());
            rbacUserRoleService.saveBatch(rolesToAddList);
        }
    }

    @PostMapping("/delete.admin")
    @ApiOperation(value = "删除", httpMethod = "POST")
    public BooleanResult delete(@RequestBody @Valid ID data) {
        return booleanResult(rbacUserService.deleteModel(data));
    }


    @PostMapping("/current/one.admin")
    @ApiOperation(value = "当前用户详情", httpMethod = "POST")
    public DataResult<RbacUserData> current() {
        Long adminId = getAdminId();
        RbacUserData user = rbacUserService.selectByID(new ID(adminId));
        user.setPassword("");
        return dataResult(user);
    }

    @PostMapping("/outLogin.admin")
    @ApiOperation(value = "登出", httpMethod = "POST")
    public BooleanResult outLogin() {
        return booleanResult(true);
    }


}

